/*
 * @(#)ScriptUtil.java	1.0 May 5, 2008
 *
 *	The MIT License
 *
 *	Copyright (c) 2008 Malachi de AElfweald <malachid@gmail.com>
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a copy
 *	of this software and associated documentation files (the "Software"), to deal
 *	in the Software without restriction, including without limitation the rights
 *	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *	copies of the Software, and to permit persons to whom the Software is
 *	furnished to do so, subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in
 *	all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *	THE SOFTWARE.
 */
package org.eoti.script;

import org.kohsuke.args4j.*;
import org.eoti.io.file.FileUtil;
import org.eoti.io.args4j.CommandLineApp;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import java.io.*;
import java.util.*;

public class ScriptUtil extends CommandLineApp
{
	@Option(name="-script", usage="specify script")
	protected File script;

	@Option(name="-function", usage="specify function")
	protected String function;

	@Option(name="-return", usage="show return value")
	protected boolean showRetVal = false;

	protected String ext;
	protected Reader reader;
	protected ScriptEngineManager engineMgr;
	protected ScriptEngine engine;
	protected Object evalRet, funcRet;


	public static void main(String[] args)
	{
		try{
			ScriptUtil su = new ScriptUtil(args);
		} catch(CmdLineException e){
			System.out.println("Exception: " + e.getMessage());
			e.printStackTrace();
			System.exit(1);
		}
	}

	public ScriptUtil(File script, String function, List<String> arguments)
			throws Exception
	{
		this.script = script;
		this.function = function;
		this.arguments = arguments;
		executeScript();
	}

	protected ScriptUtil(String[] args)
			throws CmdLineException
	{
		super(args);

		try{
			executeScript();
		} catch(Exception e){
			throw new CmdLineException("Error executing script.", e);
		}
	}

	protected void executeScript()
			throws Exception
	{
		if(script == null)
		{
			if(function != null)
				throw new Exception("Function requested, but no Script provided.");

			DisplayEngines();
			System.exit(0);
		}

		if(script.lastModified() == 0)
			throw new Exception("Script '" + script.getName() + "' not found.");

		if(script.lastModified() == 0)
			throw new IOException("I was unable to locate '" + script.getName() + "'");


		engineMgr = new ScriptEngineManager();

		ext = FileUtil.getFileExtension(script);
		engine = engineMgr.getEngineByExtension(ext);

		reader = new BufferedReader(new FileReader(script));
		evalRet = engine.eval(reader);
		if(showRetVal && (evalRet != null))
			System.out.println(evalRet);

		if(function != null)
		{
			Invocable invocableEngine = (Invocable)engine;
			if(evalRet == null)
				funcRet = invocableEngine.invokeFunction(function);
			else
				funcRet = invocableEngine.invokeMethod(evalRet,function);

			if(showRetVal && (funcRet != null))
				System.out.println(funcRet);
		}
	}

	public static void DisplayEngines()
	{
		ScriptEngineManager mgr = new ScriptEngineManager();
		List<ScriptEngineFactory> factories = mgr.getEngineFactories();

		for(ScriptEngineFactory factory : factories)
		{
			System.out.format("Script Engine: %s (%s)\n", factory.getEngineName(), factory.getEngineVersion());
			for(String name : factory.getNames())
				System.out.format("\tEngine Alias: %s\n", name);

			System.out.format("\tLanguage: %s (%s)\n", factory.getLanguageName(), factory.getLanguageVersion());
		}
	}

	public static Object RunScript(File script)
			throws Exception
	{
		ScriptUtil su = new ScriptUtil(script, null, null);
		return su.evalRet;
	}

	public static Object RunScript(File script, String function)
			throws Exception
	{
		ScriptUtil su = new ScriptUtil(script, function, null);
		return su.funcRet;
	}
}
